from dis import dis


# 函数装饰器和闭包
# 函数装饰器用于在源码中“标记”函数，以某种方式增强函数的行为
# 1、装饰器基础知识
# @decorate   --> target - decorate(target)
# def target():
#     print('running target()')

def deco(func):
    def inner():
        print('running inner()')

    return inner


@deco
def target():
    print('running target')


# 装饰器可能会处理被装饰的函数，然后把它返回，或者将其替换成另一个函数或可调用对象
target()
print(target)


# 2、Python何时执行装饰器 @see registration.py
# 装饰器在加载模块时立即执行
# 3、使用装饰器改进策略模式 @see strategy.py
# 4、变量作用域规则
def f1(a):
    print(a)
    print(b)


# 调用前声明b
b = 2
f1(3)

print("--f2--")
b2 = 6


def f2(a):
    print(a)
    # 下一行给b2赋值 作为局部变量 UnboundLocalError
    # print(b2)
    b2 = 9


f2(3)

print("--f3--")
b3 = 6


def f3(a):
    global b3  # 声明b3为全局变量
    print(a)
    print(b3)
    b3 = 9


f3(3)
print(b3)
b3 = 30
print(b3)
# 5、闭包 @see average.py
# 闭包指延伸了作用域的函数，其中包含函数定义体中引用、但是不在定义体中定义的非全局变量。
# 函数是不是匿名的没有关系，关键是 它能访问定义体之外定义的非全局变量。
# 6、nonlocal声明 @see average_2.py
# 7、实现一个简单的装饰器 @see clockdeco.py clockdeco_demo.py
# 8、标准库中的装饰器
# functools.wraps 协助构建行为良好的装饰器
# functools.lru_cache 实现了memoization功能，缓存最近的耗时的函数结果 @see fibonacci.py
# functools.singledispatch  @htmlize.py
# 9、叠放装饰器
# 把 @d1 和 @d2 两个装饰器按顺序应用到 f 函数上，作用相当于 f =d1(d2(f))
# 10、参数化装饰器
# @see registration_param.py clockdeco_param.py